package com.tangyuan.ai.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.aliyun.videoenhan20200320.models.GetAsyncJobResultResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.ai.entity.dto.ExchangeFaceDTO;
import com.tangyuan.ai.entity.dto.ExchangeFacePageDTO;
import com.tangyuan.ai.entity.enums.AiExchangeStatusEnum;
import com.tangyuan.ai.entity.model.AiExchangeFace;
import com.tangyuan.ai.mapper.AiExchangeFaceMapper;
import com.tangyuan.ai.service.AiExchangeFaceService;
import com.tangyuan.ai.util.Sample;
import com.tangyuan.common.util.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class AiExchangeFaceServiceImpl extends ServiceImpl<AiExchangeFaceMapper, AiExchangeFace> implements AiExchangeFaceService {

    @Autowired
    private Sample sample;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Page<AiExchangeFace> getUserPageExchangeFace(Long userId, ExchangeFacePageDTO dto) {
        QueryWrapper<AiExchangeFace> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AiExchangeFace::getUserId,userId);
        //默认查询一小时内的视频
        wrapper.lambda().ge(AiExchangeFace::getCreateTime,new Date(System.currentTimeMillis() - 3600000L));
        if (StringUtils.isNotEmpty(dto.getFaceName())) {
            wrapper.lambda().like(AiExchangeFace::getFaceName, dto.getFaceName());
        }
        wrapper.lambda().orderByDesc(AiExchangeFace::getCreateTime);
        // 分页查询用户的换脸数据
        Page<AiExchangeFace> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<AiExchangeFace> records = baseMapper.selectPage(page, wrapper).getRecords();
        // 过期的视频
        List<Long> faces = new ArrayList<>();
        // 进行中的视频
        for (AiExchangeFace face : records) {
            // 条件:状态值不是已过期 过期时间不为空 过期时间大于当前时间
            if (!face.getStatus().equals(AiExchangeStatusEnum.EXPIRES.getStatus())
                    && face.getExpiresTime() != null
                    && face.getExpiresTime().before(new Date())
            ) {
                faces.add(face.getId());
                // 设置已过期
                face.setStatus(AiExchangeStatusEnum.EXPIRES.getStatus());
                face.setStatusStr(AiExchangeStatusEnum.EXPIRES.getStatusStr());
            }
        }
        updateExchangeFaceStatus(faces, AiExchangeStatusEnum.EXPIRES);
        return page.setRecords(records);
    }

    @Override
    public AiExchangeFace getExchangeFaceById(Long userId, Long id) {
        AiExchangeFace face = baseMapper.selectById(id);
        if(face == null){
            return new AiExchangeFace();
        }
        if (!AiExchangeStatusEnum.QUEUING.getStatus().equals(face.getStatus())
                && !AiExchangeStatusEnum.PROCESSING.getStatus().equals(face.getStatus())) {
            return face;
        }
        GetAsyncJobResultResponseBody.GetAsyncJobResultResponseBodyData data = sample.getAsyncByJobId(face.getJobId());
        AiExchangeStatusEnum anEnum = AiExchangeStatusEnum.getEnum(data.status);
        switch (anEnum) {
            case PROCESS_FAILED:
                face.setStatus(anEnum.getStatus());
                Pattern patternEnglish = Pattern.compile("[A-Za-z\\s]");
                Matcher matcherEnglish = patternEnglish.matcher(data.errorMessage);
                face.setStatusStr(matcherEnglish.replaceAll(""));
                break;
            case PROCESS_SUCCESS:
                JSONObject videoJson = new JSONObject(data.result);
                String videoUrl = videoJson.get("videoUrl").toString();
                // 从视频链接中取出过期时间
                Pattern pattern = Pattern.compile("Expires=(\\d+)");
                Matcher matcher = pattern.matcher(videoUrl);
                if (matcher.find()) {
                    long parsed = Long.parseLong(matcher.group(1) + "000");
                    face.setExpiresTime(new Date(parsed));
                }
                face.setBackVideo(videoUrl);
            default:
                face.setStatus(anEnum.getStatus());
                face.setStatusStr(anEnum.getStatusStr());
                break;
        }
        baseMapper.updateById(face);
        return face;
    }

    @Override
    public Long saveExchangeFace(Long userId, ExchangeFaceDTO dto) {
        AiExchangeFace face = getExchangeFaceByJobId(dto.getJobId());
        if(face != null){
            //已有数据 去获取最新状态
            getExchangeFaceById(userId, face.getId());
            return face.getId();
        }
        face = BeanUtils.copyBean(dto, AiExchangeFace.class);
        face.setUserId(userId);
        face.setStatus(AiExchangeStatusEnum.QUEUING.getStatus());
        face.setStatusStr(AiExchangeStatusEnum.QUEUING.getStatusStr());
        face.setCreateTime(new Date());
        // 时间戳当名字
        if (face.getFaceName() == null) {
            face.setFaceName(String.valueOf(System.currentTimeMillis()));
        }
        baseMapper.insert(face);
        getExchangeFaceById(userId, face.getId());
        return face.getId();
    }

    public void updateExchangeFaceStatus(List<Long> ids, AiExchangeStatusEnum statusEnum) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        baseMapper.update(null, new LambdaUpdateWrapper<AiExchangeFace>()
                .in(AiExchangeFace::getId, ids)
                .set(AiExchangeFace::getStatus, statusEnum.getStatus())
                .set(AiExchangeFace::getStatusStr, statusEnum.getStatusStr())
        );
    }

    private AiExchangeFace getExchangeFaceByJobId(String jobId) {
        if (StringUtils.isEmpty(jobId)) {
            return null;
        }
        return baseMapper.selectOne(new LambdaQueryWrapper<AiExchangeFace>()
                .eq(AiExchangeFace::getJobId, jobId));
    }

}
